package com.touzhijia.common.controller;

import com.touzhijia.common.utils.DateTimeUtils;
import com.touzhijia.common.vo.response.AjaxMessage;
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyEditorSupport;
import java.util.Date;

/**
 * 统一的异常处理、数据绑定
 * <p>
 * 作者：lizw <br/>
 * 创建时间：2017/6/2 11:05 <br/>
 */
@ControllerAdvice
public class ControllerGlobalConfig {
    /**
     * 此处将键值对添加到全局，注解了@RequestMapping的方法都可以获得此键值对
     */
    @ModelAttribute
    public void addAttributes(Model model, HttpServletRequest request, HttpServletResponse response) {
        // model.addAttribute("key", "value");
    }

    /**
     * 初始化数据绑定,每个请求都会进来这个方法,每次WebDataBinder binder都会是一个新对象<br/>
     * 1.将所有传递进来的String进行HTML编码，防止XSS攻击 <br/>
     * 2.将字段中Date类型转换为String类型<br/>
     */
    @InitBinder
    public void initBinder(WebDataBinder binder, HttpServletRequest request, HttpServletResponse response) {
        // String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                // 可以设置不过滤的url路径，对于某些请求不进行HTML编码
                setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
            }

            @Override
            public String getAsText() {
                Object value = getValue();
                return value != null ? value.toString() : "";
            }
        });

        // Date 类型转换
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(DateTimeUtils.parseDate(text));
            }
        });
    }

    /**
     * 默认的异常处理方法<br/>
     * 1.返回AjaxMessage<br/>
     * 2.错误信息存到request Attribute中，给拦截器处理(存储)<br/>
     */
    @ExceptionHandler(value = Throwable.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest request, HttpServletResponse response, Throwable throwable) {
        ModelAndView modelAndView = new ModelAndView();

        // 错误信息存到request Attribute中，给拦截器处理(存储)
        request.setAttribute(BaseController.SERVER_EXCEPTION, throwable);

        // 如果是ajax请求直接返回响应数据，跳转到对应的错误页面
        if ("true".equals(request.getParameter("ajaxRequest")) || request.getRequestURI().endsWith(".json") || request.getRequestURI().endsWith(".xml")) {
            AjaxMessage<String> ajaxMessage = new AjaxMessage<>(throwable, "服务器异常!");
            ajaxMessage.setFailMessage("服务器异常!");
            modelAndView.getModelMap().put(BaseController.XML_OR_JSON_ROOT, ajaxMessage);
        }
        return modelAndView;
    }

}
